package com.gwt.theOne.theLocal.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MultiWordSuggestOracle;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.RichTextArea;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.gwt.theOne.theLocal.shared.CurrentWeather;
import com.gwt.theOne.theLocal.shared.DiggInfo;
import com.gwt.theOne.theLocal.shared.GoogleNews;
import com.gwt.theOne.theLocal.shared.LoginInfo;

public class GWTMaxiLocal implements EntryPoint {

	private VerticalPanel mainVerticalPanel = new VerticalPanel();
	private HorizontalPanel topHorizontalPanel = new HorizontalPanel();
	private HorizontalPanel bottomHorizontalPanel = new HorizontalPanel();
	private HorizontalPanel titleHorizontalPanel = new HorizontalPanel();
	private VerticalPanel topLeftVerticalPanel = new VerticalPanel();
	private VerticalPanel topCenterVerticalPanel = new VerticalPanel();
	private VerticalPanel topRightVerticalPanel = new VerticalPanel();
	private HorizontalPanel searchHorizontalPanel1 = new HorizontalPanel();
	private HorizontalPanel searchHorizontalPanel2 = new HorizontalPanel();
	private SimplePanel weatherPanel = new SimplePanel();
	private ScrollPanel googleNewsScrollPanel = new ScrollPanel();
	private VerticalPanel googleNewsDataPanel = new VerticalPanel();
	private VerticalPanel diggsPanel = new VerticalPanel();
	private ScrollPanel diggsScrollPanel = new ScrollPanel();
	private VerticalPanel diggsDataPanel = new VerticalPanel();
	private VerticalPanel userCommentsPanel = new VerticalPanel();
	private ScrollPanel userCommentsScrollPanel = new ScrollPanel();
	private VerticalPanel ucDataPanel = new VerticalPanel();
	private VerticalPanel weatherVertPanel = new VerticalPanel();
	private VerticalPanel newsPanel = new VerticalPanel();
	private final FlexTable newsTable = new FlexTable();
	private final RadioButton orderedByRelevanceRadioButton = new RadioButton("group", "Ordered by relevance");
	private final RadioButton orderedByDateRadioButton = new RadioButton("group", "Ordered by date");

	private Button goButton = new Button("Go!");
	private Button postCommentButton = new Button("Click to post comment");
	private CheckBox incNeighborCheckBox = new CheckBox();
	private Label cityNameLabel = new Label("Enter City Name ");
	private Label includeNeighborLabel = new Label(" Include Neighboring locations");
	private Label errorMsgLabel = new Label(); 
	private RadioButton sortDateRadio = new RadioButton("diggRadios");
	private RadioButton sortPopularRadio = new RadioButton("diggRadios");
	private HTML weatherHeadingHtml = new HTML("<p style=\"text-align:center;background-color:#99CCCC;font-size:14px;font-weight:bold;\">Weather</p>");
	private HTML googleNewsHeadingHtml = new HTML("<p style=\"text-align:center;background-color:#99CCCC;font-size:14px;font-weight:bold;\">Google News</p>");
	private HTML diggsHeadingHtml = new HTML("<p style=\"text-align:center;background-color:#99CCCC;font-size:14px;font-weight:bold;\">Diggs</p>");
	private HTML ucHeadingHtml = new HTML("<p style=\"text-align:center;background-color:#99CCCC;font-size:14px;font-weight:bold;\">User Comments</p>");
	private final MultiWordSuggestOracle oracle = new MultiWordSuggestOracle();
	private final SuggestBox locationText = new SuggestBox(oracle);
	private HTML signOut;
	private HTML tagline; 

	private FetchDataServiceAsync localInfoSvc = GWT.create(FetchDataService.class);
	private String locName;
	private static LoginInfo loginInfo;
	private int currentLocalRow;

	public void onModuleLoad() {

		loginCheck();
	}

	private void loadInitialPage() {
		//loadLocationNames(); //needed to be done one time only
		fetchLocationNames();
		//insertNearbyPlaces();//needed to be done one time only

		weatherVertPanel.setVisible(false);
		weatherVertPanel.setSize("415px", "160px");
		weatherVertPanel.setStylePrimaryName("x-panel");
		weatherVertPanel.add(weatherHeadingHtml);
		weatherVertPanel.add(weatherPanel);

		newsPanel.setSize("415px", "450px");
		googleNewsScrollPanel.setHeight("330px");		
		newsPanel.setStylePrimaryName("x-panel");
		newsPanel.setSpacing(5);

		buildNewsPanel();

		diggsPanel.setSize("415px", "450px");
		diggsDataPanel.setSpacing(2);
		diggsScrollPanel.setHeight("330px");
		diggsScrollPanel.add(diggsDataPanel);
		diggsPanel.setSpacing(5);
		diggsPanel.setStylePrimaryName("x-panel");
		diggsPanel.add(diggsHeadingHtml);
		diggsPanel.add(sortDateRadio);
		diggsPanel.add(sortPopularRadio);
		diggsPanel.add(diggsScrollPanel);
		sortDateRadio.setValue(true);
		sortDateRadio.setText("sort by most Recent");
		sortPopularRadio.setText("sort by most Popular");

		userCommentsPanel.setSize("415px", "450px");
		ucDataPanel.setSpacing(2);
		userCommentsScrollPanel.setHeight("350px");
		userCommentsScrollPanel.add(ucDataPanel);
		userCommentsPanel.setStylePrimaryName("x-panel");
		userCommentsPanel.setSpacing(5);
		userCommentsPanel.add(ucHeadingHtml);
		userCommentsPanel.add(postCommentButton);
		userCommentsPanel.add(userCommentsScrollPanel);	

		searchHorizontalPanel1.setSpacing(20);
		searchHorizontalPanel1.setVerticalAlignment(HasVerticalAlignment.ALIGN_BOTTOM);
		searchHorizontalPanel1.add(cityNameLabel);
		searchHorizontalPanel1.add(locationText);

		searchHorizontalPanel2.setSpacing(20);
		searchHorizontalPanel2.setVerticalAlignment(HasVerticalAlignment.ALIGN_BOTTOM);
		searchHorizontalPanel2.add(incNeighborCheckBox);
		searchHorizontalPanel2.add(includeNeighborLabel);
		searchHorizontalPanel2.add(goButton);

		signOut = new HTML("<P align=\"right\"><a href=\"" + loginInfo.getLogoutUrl() + "\">Sign out</a></p>");
		titleHorizontalPanel.setSpacing(20);
		titleHorizontalPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_BOTTOM);
		titleHorizontalPanel.add(new HTML("<h2>The Local</h2>"));
		titleHorizontalPanel.add(signOut);

		errorMsgLabel.setStyleName("errorMessage");
		errorMsgLabel.setVisible(false);

		topLeftVerticalPanel.setWidth("450px");
		topLeftVerticalPanel.setSpacing(1);
		topLeftVerticalPanel.add(titleHorizontalPanel);
		topLeftVerticalPanel.add(searchHorizontalPanel1);
		topLeftVerticalPanel.add(searchHorizontalPanel2);
		topLeftVerticalPanel.add(errorMsgLabel);

		tagline = new HTML("<p style=\"text-align:center;color:#99CCCC;font-size:14px;font-weight:bold;\">bringing you closer to <i>home</i>...</p>");
		topCenterVerticalPanel.setSize("415px","200px");
		topCenterVerticalPanel.setSpacing(10);
		topCenterVerticalPanel.add(new HTML("<img align = \"center\" src=\"/localPic.gif\"/>"));
		topCenterVerticalPanel.add(tagline);
		topRightVerticalPanel.setWidth("300px");
		topRightVerticalPanel.add(weatherVertPanel);

		topHorizontalPanel.setSpacing(7);
		topHorizontalPanel.setHeight("200px");
		topHorizontalPanel.add(topLeftVerticalPanel);
		topHorizontalPanel.add(topCenterVerticalPanel);
		topHorizontalPanel.add(topRightVerticalPanel);

		bottomHorizontalPanel.setVisible(false);
		bottomHorizontalPanel.setSpacing(20);
		bottomHorizontalPanel.add(newsPanel);
		bottomHorizontalPanel.add(diggsPanel);
		bottomHorizontalPanel.add(userCommentsPanel);

		mainVerticalPanel.setSpacing(2);
		mainVerticalPanel.setStylePrimaryName("mainVPanel");
		mainVerticalPanel.add(topHorizontalPanel);
		mainVerticalPanel.add(bottomHorizontalPanel);

		RootPanel.get("localInfo").add(mainVerticalPanel);

		goButton.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				String location = locationText.getText();
				if (location!= null && !"".equals(location))
				{
					getLocalInfo(location.trim(), incNeighborCheckBox.getValue());
				}
				else
					errorMsgLabel.setText("Please enter a valid city/location");
			}
		});

		postCommentButton.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				showWriteCommentPanel();
			}			
		});

		sortDateRadio.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				getDiggInfo(locName, incNeighborCheckBox.getValue());
			}
		});
		
		sortPopularRadio.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				getDiggInfo(locName, incNeighborCheckBox.getValue());
			}
		});
	}

	private void buildNewsPanel(){

		newsPanel.add(googleNewsHeadingHtml);
		newsPanel.add(orderedByRelevanceRadioButton);
		newsPanel.add(orderedByDateRadioButton);
		newsPanel.add(googleNewsScrollPanel);
		googleNewsScrollPanel.add(newsTable);

		orderedByRelevanceRadioButton.setValue(true);
		orderedByRelevanceRadioButton.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				getNewsInfo(locationText.getText().trim(), incNeighborCheckBox.getValue());
			}	    	
		});
		orderedByDateRadioButton.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				getNewsInfo(locationText.getText().trim(), incNeighborCheckBox.getValue());
			}	    	
		});
	}

	private void showWriteCommentPanel() {
		final PopupPanel popUpPanel = new PopupPanel();
		VerticalPanel popUpVertPanel = new VerticalPanel();
		final RichTextArea richTextArea = new RichTextArea();
		richTextArea.setSize("300px", "170px");
		RichTextToolbar toolbar = new RichTextToolbar(richTextArea);
		toolbar.setSize("300px", "100px");

		Grid richTextGrid = new Grid(2, 1);
		richTextGrid.setWidget(0, 0, toolbar);
		richTextGrid.setWidget(1, 0, richTextArea);
		HorizontalPanel horizontalButtonsPanel = new HorizontalPanel();
		horizontalButtonsPanel.setSpacing(30);
		Button submitButton = new Button("Submit");		
		Button closeButton = new Button("Close");
		submitButton.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				addUserComment(loginInfo.getNickname(),loginInfo.getEmailAddress(),richTextArea.getHTML());
				popUpPanel.hide();
			}			
		});
		closeButton.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				popUpPanel.hide();				
			}
		});
		horizontalButtonsPanel.add(submitButton);
		horizontalButtonsPanel.add(closeButton);
		popUpPanel.add(popUpVertPanel);
		popUpVertPanel.add(richTextGrid);
		popUpVertPanel.add(horizontalButtonsPanel);		
		popUpPanel.center();
	}

	private void addUserComment(String nickname,String emailAddress, String commentHtml) {
		if (localInfoSvc == null) {
			localInfoSvc = GWT.create(FetchDataService.class);
		}				
		AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>() {			

			public void onSuccess(Boolean isSuccessful) {
				errorMsgLabel.setVisible(false);
				if(isSuccessful)
					getUserComments(locName, incNeighborCheckBox.getValue());
			}

			public void onFailure(Throwable caught) {				
				String details = "";
				if (caught instanceof Exception) {
					details = "Exception Occured: " + ((Exception)caught) +caught.getMessage();
				}
				errorMsgLabel.setText("Error: " + details);
				errorMsgLabel.setVisible(true);
			}
		};

		localInfoSvc.addUserComment(locName,nickname,emailAddress,commentHtml,callback);
	}

	private void loginCheck() {
		if (localInfoSvc == null) {
			localInfoSvc = GWT.create(FetchDataService.class);
		}
		AsyncCallback<LoginInfo> callback = new AsyncCallback<LoginInfo>() {			

			public void onSuccess(LoginInfo loginInfo) {
				try{
					if(loginInfo.isLoggedIn()) {
						System.out.println("Logged in!");
						GWTMaxiLocal.loginInfo = loginInfo;    
						loadInitialPage();
					} else {
						System.out.println("Not Logged in!");
						loadLoginLink(loginInfo);
					}
				}catch(Exception e){
				}
			}			

			public void onFailure(Throwable caught) {				
				String details = "";
				if (caught instanceof Exception) {
					details = "Exception Occured: " + ((Exception)caught);
				}
				System.out.println(details);
			}
		};
		localInfoSvc.validateUserLogin(GWT.getHostPageBaseURL(), callback);
	}


	private void loadLoginLink(LoginInfo loginInfo) {
		Anchor loginLink = new Anchor("Sign In to 'The Local' using your Google Account", loginInfo.getLoginUrl());
		RootPanel.get("loginLink").add(loginLink);			
	}

	private void getLocalInfo(String location, boolean isIncludeNeighbor) {
		clearAllInfo();
		weatherVertPanel.setVisible(true);
		bottomHorizontalPanel.setVisible(true);
		getWeatherNews(location);
		getNewsInfo(location,isIncludeNeighbor);
		getDiggInfo(location,isIncludeNeighbor);
		getUserComments(location,isIncludeNeighbor);		
		locName = location;
		tagline.setHTML("<p style=\"text-align:center;color:#99CCCC;font-size:14px;font-weight:bold;\">bringing you closer to <i>home</i>... <b>"+locName+"!</b></p>");
	}	

	private void clearAllInfo() {
		weatherPanel.clear();
		googleNewsDataPanel.clear();
		diggsDataPanel.clear();
		ucDataPanel.clear();
	}

	private void getWeatherNews(String cityName) {
		if(localInfoSvc == null)
			localInfoSvc = GWT.create(FetchDataService.class);
		AsyncCallback<CurrentWeather> callback = new AsyncCallback<CurrentWeather>(){
			public void onFailure(Throwable caught) {
				displayError(weatherPanel, "Could not get weather info");
			}

			public void onSuccess(CurrentWeather currWeather) {
				try{
					displayWeatherInfo(currWeather);
				}catch(Exception e){
					displayError(weatherPanel, "Could not get weather info");
				}
			}
		};
		localInfoSvc.getWeatherNews(cityName, callback);
	}

	private void displayError(SimplePanel panel, String error) {
		panel.clear();
		panel.add(new HTML("<font size=\"5px\" color=\"red\">" + error + "</font>"));
	}

	private void displayWeatherInfo(CurrentWeather currWeather){
		weatherPanel.clear();
		if(currWeather == null)
		{
			weatherPanel.add(new HTML(" Sorry! Weather information not present for this location."));			
		}
		else
		{
			HorizontalPanel h_Panel = new HorizontalPanel();

			h_Panel.setSpacing(9);
			VerticalPanel v_Panel1 = new VerticalPanel();
			VerticalPanel v_Panel2 = new VerticalPanel();
			VerticalPanel v_Panel3 = new VerticalPanel();
			v_Panel1.setStyleName("textHTML");
			v_Panel2.setStyleName("textHTML");
			v_Panel3.setStyleName("textHTML");
			HTML temperature = new HTML("<h5>"+currWeather.getTemperature()+"<sup>o</sup>F</h5>");
			HTML desc = new HTML("<h5>"+currWeather.getWeatherDescription()+"</h5>");
			HTML wind = new HTML("<h5>"+currWeather.getWindSpeed()+" mph from "+currWeather.getWindDir()+"</h5>");
			v_Panel1.add(temperature);
			v_Panel1.add(desc);
			v_Panel1.add(wind);

			HTML humid = new HTML("<h5>Humidity : "+currWeather.getHumidity()+"%</h5>");
			HTML cloudCover = new HTML("<h5>Cloud Cover : "+currWeather.getCloudCover()+"%</h5>");
			HTML pressure = new HTML("<h5>Pressure : "+currWeather.getPressure()+" mb</h5>");
			v_Panel2.add(humid);
			v_Panel2.add(cloudCover);
			v_Panel2.add(pressure);

			Image image = new Image(currWeather.getWeatherImage());
			v_Panel3.setSpacing(20);
			v_Panel3.add(new HTML());
			v_Panel3.add(image);

			h_Panel.add(v_Panel1);
			h_Panel.add(v_Panel2);
			h_Panel.add(v_Panel3);
			weatherPanel.add(h_Panel);
		}
	}

	private void getUserComments(String location, boolean isIncNeighborChked) {
		ucDataPanel.clear();
		try {
			if(localInfoSvc == null)
				localInfoSvc = GWT.create(FetchDataService.class);
			AsyncCallback<String[][]> callback = new AsyncCallback<String[][]>(){
				public void onFailure(Throwable caught) {
				}

				public void onSuccess(String[][] userComments) {
					if(userComments.length==0)
					{
						ucDataPanel.add(new HTML("Be the first one to add a comment!"));
					}
					else
					{
						try{
							for(String[] userComment: userComments){
								if(userComment[0]!=null)
								{
									ucDataPanel.add(new HTML("<b><font color=\"blue\">"+userComment[0]+":</font></b>"));
									ucDataPanel.add(new HTML(userComment[1]));
								}
							}
						}catch(Exception e){
						}
					}
				}
			};
			localInfoSvc.getUserComments(location,isIncNeighborChked,callback);
		}catch(Exception e){
		}
	}

	private void getDiggInfo(String location, boolean isIncNeighborChked) {		
		diggsDataPanel.clear();
		if (localInfoSvc == null) {
			localInfoSvc = GWT.create(FetchDataService.class);
		}				
		AsyncCallback<DiggInfo[]> callback = new AsyncCallback<DiggInfo[]>() {			

			public void onSuccess(DiggInfo[] result) {
				errorMsgLabel.setVisible(false);
				if(result.length>0)
				{
					displayDiggs(result);
				}
				else
				{
					diggsDataPanel.add(new HTML("Sorry failed to get digg data. Please try again!"));
				}
			}

			public void onFailure(Throwable caught) {				
				System.out.println("failed to get digg data");
			}
		};

		localInfoSvc.getDiggInfo(location,sortDateRadio.getValue(),isIncNeighborChked, callback);
	}

	private void displayDiggs(DiggInfo[] result) {
		String htmlStr;

		for (int i = 0; i < result.length; ++i) {

			htmlStr = "<a target=\"_blank\" href=\"" + result[i].getHref() + "\">" + result[i].getTitle()+"</a><br/>"+result[i].getDescription();
			diggsDataPanel.add(new HTML(htmlStr));
		}
	}

	private void loadLocationNames() {
		try{
			if(localInfoSvc == null)
				localInfoSvc = GWT.create(FetchDataService.class);
			AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>(){
				public void onFailure(Throwable caught) {
					System.err.println("error in loading location data");
				}

				public void onSuccess(Boolean isSuccess) {
					try{
						System.out.println("loaded location data");
					}catch(Exception e){
					}
				}
			};
			localInfoSvc.loadLocationNames(callback);
		}catch(Exception e){
		}
	}

	private void fetchLocationNames()
	{
		try {
			if(localInfoSvc == null)
				localInfoSvc = GWT.create(FetchDataService.class);
			AsyncCallback<String[]> callback = new AsyncCallback<String[]>(){
				public void onFailure(Throwable caught) {
				}

				public void onSuccess(String[] locationNames) {
					try{
						for(String locationName: locationNames){
							oracle.add(locationName);
						}
					}catch(Exception e){
					}
				}
			};
			localInfoSvc.getLocationNames(callback);
		}catch(Exception e){
		}
	}

	private void getNewsInfo(String location, boolean includeNearbyCities){

		for (int i = 0; newsTable.getRowCount() > 0; ++i) {
			newsTable.removeRow(0);
		}

		if(localInfoSvc == null){
			localInfoSvc = GWT.create(FetchDataService.class);
		}

		localInfoSvc.getNews(location, orderedByRelevanceRadioButton.getValue(), includeNearbyCities, new AsyncCallback<GoogleNews[]>() {

			@Override
			public void onSuccess(GoogleNews[] result) {
				if (result.length==0)
				{ 
					currentLocalRow++;
					newsTable.setHTML(currentLocalRow, 0, "Google News data could not be obtained for this location");
				}
				else
				{
					System.out.println("getNews returned with success");

					for (int i = 0; i < result.length; i++) {
						currentLocalRow++;

						GoogleNews story = result[i]; 
						String imgURL = story.getImageurl();

						newsTable.setHTML(currentLocalRow, 0, "<a target=\"_blank\" href=\"" + story.getUrl()
								+ "\">" + story.getTitle() + "</a> <br>" + story.getContent());

						if (imgURL != null){
							newsTable.setHTML(currentLocalRow, 1, "<img src=\"" + imgURL + "\">");
						}
					}
				}
			}

			@Override
			public void onFailure(Throwable caught) {
				System.out.println("getNews returned with failure");

			}
		});
		currentLocalRow = 0;
	}

	private void insertNearbyPlaces() {
		try{
			if(localInfoSvc == null){
				localInfoSvc = GWT.create(FetchDataService.class);
			}
			AsyncCallback<Boolean> callback = new AsyncCallback<Boolean>(){
				public void onFailure(Throwable caught) {
					System.out.println("insertNearbyPlaces returned with failure");
				}

				public void onSuccess(Boolean isSuccess) {
					try{
						System.out.println("NearbyPlaces inserted: " + isSuccess);
					}catch(Exception e){
					}
				}
			};
			localInfoSvc.insertNearbyPlacesIntoDatabase(callback);
		}catch(Exception e){
		}
	}
}